#include "SphereShape.h"
#include <cmath>
#include "../../common/Common.h"

SphereShape::SphereShape(Point poisition, float radius) {
	Vector size = Vector(radius, radius, radius);
	this->position->from(poisition);
	this->rotation = new QQuaternion(0, 0, 0, 1);
	this->radius = radius;
}

void SphereShape::init() {
	int Y_SEGMENTS = 50;
	int X_SEGMENTS = 50;
	int currentIndex = 0;
	this->points = new Point[(Y_SEGMENTS + 1) * (X_SEGMENTS + 1)];
	for (int y = 0; y <= Y_SEGMENTS; y++)
	{
		for (int x = 0; x <= X_SEGMENTS; x++)
		{
			float xSegment = (float)x / (float)X_SEGMENTS;
			float ySegment = (float)y / (float)Y_SEGMENTS;
			float xPos = std::cos(xSegment * 2.0f * M_PI) * std::sin(ySegment * M_PI);
			float yPos = std::cos(ySegment * M_PI);
			float zPos = std::sin(xSegment * 2.0f * M_PI) * std::sin(ySegment * M_PI);
			this->points[currentIndex] = Point(xPos * radius, yPos * radius, zPos * radius);
		}
	}
	this->vertexSize = (Y_SEGMENTS + 1) * (X_SEGMENTS + 1) * 6;
	this->vertex = new float[this->vertexSize];
	for (int y = 0; y <= Y_SEGMENTS; y++)
	{
		for (int x = 0; x <= X_SEGMENTS; x++)
		{
			float xSegment = (float)x / (float)X_SEGMENTS;
			float ySegment = (float)y / (float)Y_SEGMENTS;
			float xPos = std::cos(xSegment * 2.0f * M_PI) * std::sin(ySegment * M_PI);
			float yPos = std::cos(ySegment * M_PI);
			float zPos = std::sin(xSegment * 2.0f * M_PI) * std::sin(ySegment * M_PI);
			this->vertex[currentIndex++] = xPos * radius;
			this->vertex[currentIndex++] = yPos * radius;
			this->vertex[currentIndex++] = zPos * radius;
			// Normals are the same as the position in this case
			// but you can calculate them separately if needed
			// For a sphere, normals are just the normalized position vector
			// So we can just use the position as the normal
			// This is a simplification, as normals should be unit vectors
			// but since we are using the position as the normal, we can just use the position
			// as the normal directly.
			// In a more complex shape, you would calculate the normal based on the surrounding vertices.
			// Here we are just using the position as the normal
			// This is a simplification, as normals should be unit vectors
			Point normal = Point(xPos, yPos, zPos);
			normal.normalize(); // Ensure the normal is a unit vector
			this->vertex[currentIndex++] = normal.x();
			this->vertex[currentIndex++] = normal.y();
			this->vertex[currentIndex++] = normal.z();
		}
	}


	this->vbo->create();
	this->vbo->bind();
	this->vbo->allocate(this->getVertex(), this->getVertexSize() * sizeof(float));
	this->vbo->release();


	this->indexSize = Y_SEGMENTS * X_SEGMENTS * 6;
	this->indexes = new unsigned int[Y_SEGMENTS * X_SEGMENTS * 6];
	currentIndex = 0;
	for (int i = 0; i < Y_SEGMENTS;i++)
	{
		for (int j = 0; j < X_SEGMENTS;j++)
		{
			this->indexes[currentIndex++] = (i * (X_SEGMENTS + 1) + j);
			this->indexes[currentIndex++] = ((i + 1) * (X_SEGMENTS + 1) + j);
			this->indexes[currentIndex++] = ((i + 1) * (X_SEGMENTS + 1) + j + 1);

			this->indexes[currentIndex++] = (i * (X_SEGMENTS + 1) + j);
			this->indexes[currentIndex++] = ((i + 1) * (X_SEGMENTS + 1) + j + 1);
			this->indexes[currentIndex++] = (i * (X_SEGMENTS + 1) + j + 1);

		}
	}
	this->ebo->create();
	this->ebo->bind();
	this->ebo->allocate(this->getIndexes(), this->getIndexSize() * sizeof(unsigned int));
	this->ebo->release();
}